package edu.mse.camel.client.serverlib;

import java.util.List;

import camel.client.BriefSessionInfo;
import camel.client.CamelRemote;
import camel.client.ParticipantLoginInfo;
import camel.client.ParticipantStatus;
import camel.client.SessionTicket;
import camel.client.TeamMemberStatus;
import edu.mse.camel.client.eventbus.pubsub.EventManager;
import edu.mse.camel.client.events.peer.SendGenericPeerEvent;
import edu.mse.camel.client.events.peer.SendInvitationEvent;
import edu.mse.camel.client.events.server.AssignRoleEvent;
import edu.mse.camel.client.events.server.CreateSessionEvent;
import edu.mse.camel.client.events.server.JoinSessionEvent;
import edu.mse.camel.client.events.server.LeaveSessionEvent;
import edu.mse.camel.client.events.server.LoginEvent;
import edu.mse.camel.client.events.server.LogoutEvent;
import edu.mse.camel.client.events.server.NotifyLoginStatusChange;
import edu.mse.camel.client.events.server.NotifySessionParticipantChange;
import edu.mse.camel.client.events.server.NotifySessionRoleChange;
import edu.mse.camel.client.events.server.QueryLoginStatus;
import edu.mse.camel.client.events.server.QuerySessionListEvent;
import edu.mse.camel.client.events.server.SemaphoreEvent;
import edu.mse.camel.client.session.team.QuerySessionParticipantStatus;
import edu.mse.camel.client.session.team.QueryTeamStatus;
import edu.mse.camel.client.session.team.QueryTeamStatus.TeamMemberInternal;
import edu.mse.camel.client.log.Debug;

import camel.client.BriefSessionInfo;
import camel.client.ParticipantLoginInfo;
import camel.client.CamelRemote;
import camel.client.ParticipantStatus;
import camel.client.SessionTicket;
import camel.client.TeamMemberStatus;

public class SessionManagement {
	
	private void NotifySessionChange (SessionTicket ticket) {
		NotifySessionParticipantChange change = new NotifySessionParticipantChange();
		change.setInSession(ticket.isInSession());
		EventManager.getInstance().dispatchEventAsynchronous(change);
	}

	public SessionTicket login(CamelRemote remote , LoginEvent event) {
		
		event.setOpSuccessful(false);
		if ( remote == null) {
			return null;
		}
		
		SessionTicket ticket = null;
		try {
				ParticipantLoginInfo info = new ParticipantLoginInfo();
				
				info.setUsername(event.getUsername());
				info.setPassword(event.getPassword());
				ticket =  remote.login(info);
				
				if (ticket == null) {
					event.setOpSuccessful(false);
				}
				else {
					event.setOpSuccessful(ticket.isLogInSuccessful());
					Debug.log_info(Activator.PLUGIN_ID, "login " + event.isOpSuccessful() );   

					NotifyLoginStatusChange loginChange = new NotifyLoginStatusChange();
					if(ticket.isLogInSuccessful()) {
						loginChange.setLoggedIn(true);
						loginChange.setId(ticket.getUsername());
					}
					else {
						loginChange.setLoggedIn(false);
					}
					EventManager.getInstance().dispatchEventAsynchronous(loginChange);
				}
		
		}catch (Exception ex) {ex.printStackTrace();}
		

		return ticket;
	}
    
	public SessionTicket createSession(SessionTicket ticket, CamelRemote remote, CreateSessionEvent  event) {
		
		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return null;
		}
		
		try {
			  ticket = remote.createSession(ticket, event.getSessionName(),event.getSessionDesc());
			  if (ticket == null)  {
			      event.setOpSuccessful(false);
			  }
			  else {
				  event.setOpSuccessful(ticket.isInSession());
			  }
			  Debug.log_info(Activator.PLUGIN_ID, "createSession " + event.isOpSuccessful() );   
		}catch(Exception ex) {ex.printStackTrace();}
		
		NotifySessionChange(ticket);		
		return ticket;
    }
	
	
	public void  getSessionList(SessionTicket ticket,CamelRemote remote,QuerySessionListEvent event) {

		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return;
		}
		
		List<BriefSessionInfo> sessions;
		try {
		
			sessions = remote.getSessionList(ticket);
			 
			if (sessions == null)  {
				event.setQueryAnswered(false);
			}
			 else {
			     event.setQueryAnswered(true);
			     event.setOpSuccessful(true);
			 }
			 Debug.log_info(Activator.PLUGIN_ID, " getSessionList" + event.isQueryAnswered());  
	         
			 for(BriefSessionInfo info:sessions) {
				 QuerySessionListEvent.SessionList  sl  = event.getNewSessionList();
				 sl.setSessionId(info.getSessionId());
				 sl.setTimeCreated(info.getTimeCreated());
				 sl.setTimeLastUpdated(info.getTimeLastUpdated());
				 sl.setTitle(info.getTitle());
				 sl.setCreator(info.getCreator());
				 sl.setDescription(info.getDescription());
				 sl.setParticipantList(info.getParticipants());
				 sl.setPlaybackOnly(info.getPlaybackOnly());
				 event.getSessionList().add(sl);
			 }
			 Debug.log_info(Activator.PLUGIN_ID, "getSessionList " + event.isOpSuccessful() );
		}catch(Exception ex) {ex.printStackTrace();}
    }
	
	public SessionTicket joinSession(SessionTicket ticket,CamelRemote remote,JoinSessionEvent event) {
		
		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return null;
		}
		
		try {
			 ticket = remote.joinSession(ticket,event.getSessionId(), event.isPlayback());
			 if (ticket == null)  {
				  event.setOpSuccessful(false);
			 }
			 else {
				  event.setOpSuccessful(ticket.isInSession());
			 }
			  Debug.log_info(Activator.PLUGIN_ID, "joinSession " + event.isOpSuccessful() );   
		}catch(Exception ex) {ex.printStackTrace();}
		
		NotifySessionChange(ticket);
		return ticket;
    }

	public void logout(SessionTicket ticket,CamelRemote remote,LogoutEvent event) {
		
		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return;
		}
		
		try {
			 remote.logout(ticket);
			 if (ticket == null)  {
				  event.setOpSuccessful(false);
			 }
			 else {
				  event.setOpSuccessful(true);
			 }
			  Debug.log_info(Activator.PLUGIN_ID, "logout " + event.isOpSuccessful() );   
			  
		}catch(Exception ex) {ex.printStackTrace();}
		
		NotifyLoginStatusChange loginChange = new NotifyLoginStatusChange();
		loginChange.setLoggedIn(false);
		EventManager.getInstance().dispatchEventAsynchronous(loginChange);
   }
	
	public void querySessionParticipantStatus(SessionTicket ticket,CamelRemote remote,QuerySessionParticipantStatus event) {

		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return;
		}

		try {
			List<camel.client.ParticipantStatus> statusList = remote.queryParticipantStatus(ticket);
			 if (statusList == null)  {
				  event.setOpSuccessful(false);
			 }
			 else {
				 for ( ParticipantStatus status : statusList ) {
					 QuerySessionParticipantStatus.ParticipantInternal copyStatus = event.new ParticipantInternal();
					 copyStatus.setId(status.getId());
					 copyStatus.setStatusDesc(status.getStatusDesc());
					 copyStatus.setColor(status.getColor());
					 copyStatus.setFacilitator(status.isFacilitator());
					 event.getParticipants().add(copyStatus);
				 }
				  event.setOpSuccessful(true);
			 }
			  Debug.log_info(Activator.PLUGIN_ID, "querySessionParticipantStatus " + event.isOpSuccessful() );   
		}catch(Exception ex) {ex.printStackTrace();}
    }

	public void QueryLoginStatus(SessionTicket ticket,CamelRemote remote,QueryLoginStatus event) {
		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return;
		}

		try {
			event.setOpSuccessful(true);
			if ( ticket != null ) {
				event.setLoggedIn(ticket.isLogInSuccessful());
				event.setUserId(ticket.getUsername());
				event.setOpSuccessful(true);
			}
			else {
				event.setLoggedIn(false);
			}
			Debug.log_info(Activator.PLUGIN_ID, "QueryLoginStatus " + event.isOpSuccessful() );   
		}catch(Exception ex) {ex.printStackTrace();}
    }
	
	public void SemaphoreOp(SessionTicket ticket,CamelRemote remote, SemaphoreEvent  event) {
		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return;
		}
		
		try {
			if(event.getOp() == SemaphoreEvent.SemaphoreOperation.Create) {
				int id = remote.CreateSemaphore(ticket);
				if(id >= 0) {
					event.setOpSuccessful(true);
					event.setId(id);
					event.setIdValid(true);
					Debug.log_info(Activator.PLUGIN_ID, "Semaphore created : " + id );
				}
				else {
					event.setIdValid(false);
					Debug.log_warning(Activator.PLUGIN_ID, "Semaphore creation failed" );
				}
			}
			else if (event.getOp() == SemaphoreEvent.SemaphoreOperation.Release){
				if(event.isIdValid()) {
					ticket = remote.ReleaseSemaphore(ticket, event.getId());
					if(ticket.isLastOpSuccessful()) {
						Debug.log_info(Activator.PLUGIN_ID, "Semaphore released : " + event.getId() );
						event.setOpSuccessful(true);
					}
					else {
						Debug.log_info(Activator.PLUGIN_ID, "Semaphore still locked : " + event.getId() );
					}
				}
				else {
					Debug.log_error(Activator.PLUGIN_ID, "Semaphore id invalid" );
				}
			}
			else if (event.getOp() == SemaphoreEvent.SemaphoreOperation.TryAcquire){
				if(event.isIdValid()) {
					ticket = remote.TryAcquireSemaphore(ticket, event.getId());
					if(ticket.isLastOpSuccessful()) {
						Debug.log_info(Activator.PLUGIN_ID, "Semaphore acquired : " + event.getId() );
						event.setOpSuccessful(true);
					}
					else {
						Debug.log_info(Activator.PLUGIN_ID, "Semaphore still locked by someone else : " + event.getId() );
					}
				}
				else {
					Debug.log_error(Activator.PLUGIN_ID, "Semaphore id invalid" );
				}
			}
			else {
				Debug.log_error(Activator.PLUGIN_ID, "SemaphoreOp unknown" );
			}
			
		}catch(Exception ex) {ex.printStackTrace();}
	}
	
	public void QueryTeamStatus(SessionTicket ticket,CamelRemote remote, QueryTeamStatus  event) {

		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return;
		}

		List<TeamMemberStatus> teamMemberStatus;
		try {
			teamMemberStatus = remote.queryTeamMemberStatus(ticket);
			if (teamMemberStatus  == null)  {
				event.setQueryAnswered(false);
			}
			 else {
			     event.setQueryAnswered(true);
			     event.setOpSuccessful(true);
			 }
			 for (TeamMemberStatus tms: teamMemberStatus) {
			    QueryTeamStatus.TeamMemberInternal  tm  = event.getNewTeamMemberList();
				tm.setId(tms.getId());
				tm.setContact1(tms.getContact1());
				tm.setContact2(tms.getContact2());
				tm.setOnline(tms.isOnline());
	
				event.getTeamMemberList().add(tm);
			 }
		    event.setOpSuccessful(true);
			 
			Debug.log_info(Activator.PLUGIN_ID, "teamStatus " + event.isOpSuccessful() );
		}catch(Exception ex) {ex.printStackTrace();}
	}
	
	public SessionTicket leaveSession(SessionTicket ticket,CamelRemote remote,LeaveSessionEvent event) {

		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return null;
		}

		try {
			ticket = remote.leaveSession(ticket,ticket.getSessionId());
			if (ticket == null)  {
			  event.setOpSuccessful(false);
			}
			else {
			  event.setOpSuccessful(ticket.isLastOpSuccessful());
			}
			Debug.log_info(Activator.PLUGIN_ID, "leave session " + event.isOpSuccessful() );   
			  
		}catch(Exception ex) {ex.printStackTrace();}
		
		NotifySessionChange(ticket);
		return ticket;
   }
	public SessionTicket assignRole(SessionTicket ticket,CamelRemote remote,AssignRoleEvent event) {

		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return null;
		}

		try {
			 ticket = remote.assignRole(ticket, event.getUsername(),event.getRole());
			 if (ticket == null)  {
				  event.setOpSuccessful(false);
			 }
			 else {
				 event.setOpSuccessful(ticket.isLastOpSuccessful());
				 NotifySessionRoleChange  roleChange = new NotifySessionRoleChange();
				 roleChange.setRoleChange(true);
				 EventManager.getInstance().dispatchEventAsynchronous(roleChange);
			 }
			  Debug.log_info(Activator.PLUGIN_ID, "assign role " + event.isOpSuccessful() );   
			 }catch(Exception ex) {ex.printStackTrace();}
   //NotifySessionChange(ticket);
	return ticket;
   }
	
	public SessionTicket invite(SessionTicket ticket,CamelRemote remote,SendInvitationEvent event) {

		event.setOpSuccessful(false);
		if ( ticket == null || remote == null) {
			return null;
		}

		try {
			ticket = remote.invite(ticket, event.getInvitee());
			if ( ticket != null ) {
				event.setOpSuccessful(ticket.isLastOpSuccessful());
				Debug.log_info(Activator.PLUGIN_ID, "invite " + ticket.isLastOpSuccessful() );   
			}
			else {
				Debug.log_warning(Activator.PLUGIN_ID, "invite : failed with null result" );   
			}
		}catch(Exception ex) {ex.printStackTrace();}
		
		return ticket;
    }

}
